package com.by.basicgateway.event;

import com.alibaba.fastjson2.JSON;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author Tian Wei
 * @version 1.0
 * @date 2023/12/20 3:04 PM
 */

@Slf4j
@Component
public class NacosGatewayRouteChangeEventOperate implements ApplicationEventPublisherAware {

    /**
     * 路由写入事件
     */
    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;

    /**
     * 发布事件
     */
    private ApplicationEventPublisher publisher;

    /**
     * 将路由信息存放,nacos数据推送后判断信息是否有变更,如果发生变,则进行信息更新,如果没有变更则过滤
     */
    private static final Map<String,RouteDefinition> ROUTE_ID_AND_ROUTE_OBJ_MAP = new HashMap<>();

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }


    /**
     * 机器第一次启动时使用,增加路由
     */
    public synchronized void add(RouteDefinition definition) {

        try {

            String id = definition.getId();
            if (StringUtils.isEmpty(id)) {
                log.error("[NacosGatewayRouteChangeEventOperate][add] 初始化网关由错误,路由id不能为空,路由信息为:{}", JSON.toJSONString(definition));
                return;
            }

            RouteDefinition routeDefinition = ROUTE_ID_AND_ROUTE_OBJ_MAP.get(id);
            if (Objects.nonNull(routeDefinition)) {
                log.error("[NacosGatewayRouteChangeEventOperate][add] 初始化网关路由错误,路由id重复,路由信息为:{}",JSON.toJSONString(definition));
                return;
            }

            routeDefinitionWriter.save(Mono.just(definition)).subscribe();
            ROUTE_ID_AND_ROUTE_OBJ_MAP.put(id,definition);

        }catch (Exception e){
            log.error("[NacosGatewayRouteChangeEventOperate][add] 网关路由信息新增异常:{}", ExceptionUtils.getMessage(e));
        }

    }

    /**
     * 更新路由
     */
    public synchronized void updateById(RouteDefinition definition) {
        try {

            String id = definition.getId();
            if (StringUtils.isEmpty(id)) {
                log.error("[NacosGatewayRouteChangeEventOperate][updateById] 路由编辑错误,路由id不能为空");
                return;
            }

            RouteDefinition oldRouteDefinition = ROUTE_ID_AND_ROUTE_OBJ_MAP.get(id);
            //如果为空则新增
            if (Objects.isNull(oldRouteDefinition)) {
                this.add(definition);
                return;
            }

            //修改,判断新老路由信息是否相同,相同则不进行修改
            if (Objects.equals(definition.toString(),oldRouteDefinition.toString())) {
                log.info("[NacosGatewayRouteChangeEventOperate][updateById] ");
                return;
            }
            this.delete(id);
            this.add(definition);
        } catch (Exception e) {
            log.info("[NacosGatewayRouteChangeEventOperate][updateById] 网关路由信息修改异常:{}", ExceptionUtils.getMessage(e));
        }
    }

    /**
     * 删除路由
     */
    public synchronized void delete(String id) {

        try {
            if (StringUtils.isEmpty(id)) {
                log.error("[NacosGatewayRouteChangeEventOperate][delete] 路由删除错误,路由id不能为空");
                return;
            }

            RouteDefinition routeDefinition = ROUTE_ID_AND_ROUTE_OBJ_MAP.get(id);
            if (Objects.isNull(routeDefinition)) {
                log.error("[NacosGatewayRouteChangeEventOperate][delete] 网关路由删除错误,路由信息不存在,路由信息id为:{}",JSON.toJSONString(routeDefinition));
                return;
            }

            this.routeDefinitionWriter.delete(Mono.just(id)).subscribe();
            ROUTE_ID_AND_ROUTE_OBJ_MAP.remove(id);
        } catch (Exception e) {
            log.error("[NacosGatewayRouteChangeEventOperate][delete] 网管路由信息删除异常:{}", ExceptionUtils.getMessage(e));
        }

    }

    public static Map<String,RouteDefinition> getCurrentRouteInfoMap(){
        return Maps.newHashMap(ROUTE_ID_AND_ROUTE_OBJ_MAP);
    }

    //刷新路由信息
    public synchronized void refreshAll(List<Runnable> runnableList){

        runnableList.forEach(Runnable::run);
        //整体数据运行完成后推送路由更新事件
        this.publisher.publishEvent(new RefreshRoutesEvent(routeDefinitionWriter));

    }

}
